package com.vinjogames.gfx;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.PointF;

import com.vinjogames.util.GameConVars;

public class Gun {
	public static final float GLWIDTH = 1;
	public static final float GLHEIGHT = .25f;
	public static final float MAXANGLE = 80f;
	public static final float MINANGLE = 0;
	
	private Image mImage;
	private float mAngle;
	private PointF mOffset;
	
	private float mLength;
	private PointF mLocation;
	private float mBaseAngle;
	private float mTempHyp;
	private float mTempAngle;
	private float sign;
	public float desiredAngle;
	
	private boolean readyToShoot;

	//Offsets
	public static final PointF MORTIMER = new PointF(-0.1f,0.01f);
	public static final PointF ABRAMS = new PointF(0.01f,-0.1f);
	public static final PointF BLUEBOY = new PointF(-0.15f,0.1f);
	public static final PointF DILLO = new PointF(-0.15f,0.1f);
	public static final PointF FLY = new PointF(-0.03f,-0.82f);
	public static final PointF PINKY = new PointF(0.01f,0.3f);
	public static final PointF SNIPPY = new PointF(-0.3f,0.01f);
	public static final PointF TURRET = new PointF(0.01f,0.3f);
	
	//Lengths(?)
	public static final float MORTIMERLENGTH = 0.75f;
	public static final float ABRAMSLENGTH = 0.9f;
	public static final float BLUEBOYLENGTH = 0.3f;
	public static final float DILLOLENGTH = 1f;
	public static final float FLYLENGTH = 1f;
	public static final float PINKYLENGTH = 0.05f;
	public static final float SNIPPYLENGTH = 0.5f;
	public static final float TURRET_LENGTH = 0.5f;
	
	public Gun(int type, PointF offset, float length){
		mOffset = offset;
        mImage = new Image(type, GLWIDTH, GLHEIGHT);
        mLength = length;
        mImage.setLeftPivot();
        mLocation = new PointF();
	}
	
	public void draw(GL10 gl, PointF location, float baseAngle){
		mBaseAngle = baseAngle;
		mImage.rotate(mBaseAngle + mAngle);
		mTempAngle = (float) (Math.atan(mOffset.y / mOffset.x) + Math.toRadians(mBaseAngle));
		mTempHyp = mOffset.length();
		sign = Math.signum(mOffset.x) * Math.signum(mOffset.y);
		//TODO Check on a curve.
		if(!mImage.isFlipped()){
			mLocation.x = (float) (location.x + Math.cos(mTempAngle) * mTempHyp * Math.signum(mOffset.x));
			if(Math.sin(mTempAngle) < 0)
				mLocation.y = (float) (location.y + Math.sin(mTempAngle) * mTempHyp);
			else{
				mLocation.y = (float) (location.y + (sign) * Math.sin(mTempAngle) * mTempHyp);
			}
		}else{ 
			if(Math.atan(mOffset.y / mOffset.x) > 0){
				mLocation.x = (float) (location.x + Math.cos(mTempAngle) * mTempHyp * Math.signum(mOffset.x));
			}
			else mLocation.x = (float) (location.x - Math.cos(mTempAngle) * mTempHyp * Math.signum(mOffset.x));
			if(Math.atan(mOffset.y / mOffset.x) > 0)
				mLocation.y = (float) (location.y + (sign) * Math.sin(mTempAngle) * mTempHyp);
			else{
				mLocation.y = (float) (location.y + (sign) * Math.sin(mTempAngle) * mTempHyp);
			}
		}
		mImage.draw(gl, mLocation);
	}
	
	public void drawShadow(GL10 gl, PointF location, float angle){
		mImage.rotate(angle);
		mImage.draw(gl, location.x, location.y,1,1,1,.5f);
	}
	
	public PointF calculateMuzzleLocation(){
		// TODO Fix 0.5f in y.
		mTempHyp = mOffset.length();
		if(mImage.isFlipped())
			return new PointF((float) (getX() - Math.cos(Math.toRadians(mAngle + mBaseAngle)) * (mTempHyp) - Math.cos(Math.toRadians(mAngle + mBaseAngle)) * mLength),
					(float) (getY() + Math.sin(Math.toRadians(mAngle + mBaseAngle)) * (mTempHyp) + Math.sin(Math.toRadians(mAngle + mBaseAngle)) * mLength));
		return new PointF((float) (getX() + Math.cos(Math.toRadians(mAngle + mBaseAngle)) * (mTempHyp) + Math.cos(Math.toRadians(mAngle + mBaseAngle)) * mLength),
				(float) (getY() + Math.sin(Math.toRadians(mAngle + mBaseAngle)) * (mTempHyp) + Math.sin(Math.toRadians(mAngle + mBaseAngle)) * mLength));
	}
	
	public void angleUp(){ 
		mAngle = mAngle + GameConVars.GUN_ROTATION_CHANGE_SPEED > MAXANGLE ? MAXANGLE : mAngle+GameConVars.GUN_ROTATION_CHANGE_SPEED;
	}
	
	public void angleDown(){
		mAngle = mAngle - GameConVars.GUN_ROTATION_CHANGE_SPEED < MINANGLE ? MINANGLE : mAngle-GameConVars.GUN_ROTATION_CHANGE_SPEED; 
	}
	public void setQuickAngle(float angle){
		desiredAngle = angle;
		readyToShoot = false;
		
		if(angle <= MINANGLE){
			mAngle = MINANGLE;
			readyToShoot = true;
		}
		else if(angle >= MAXANGLE){
			mAngle = MAXANGLE;
			readyToShoot = true;
		}
		else {
			mAngle = angle; 
			readyToShoot = true;
		}
	}
	public void setAngle(float angle){
		desiredAngle = angle;
		readyToShoot = false;
		
		if(angle < mAngle - GameConVars.GUN_ROTATION_CHANGE_SPEED)
			angleDown();
		else if(angle > mAngle + GameConVars.GUN_ROTATION_CHANGE_SPEED)
			angleUp();
		else {
			mAngle = angle;
			readyToShoot = true;
		}
	}
	
	public boolean isReadyToShoot(){
		return readyToShoot;
	}
	
	public void setOffset(PointF p){ mOffset = p; }
	public PointF getOffset(){ return mOffset; }
	public float getAngle(){ return mAngle; }
	public Image getImage(){ return mImage; }
	public PointF getLocation(){ return mLocation; }
	public float getLength(){ return mLength; }
	
	public float getX(){ return mLocation.x; }
	// The half of the Unit's Image Height.
	public float getY(){ return mLocation.y + .5f; }
}
